using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Drawing.Imaging;
using System.Threading;
using PocketLibrary.Image;
using Microsoft.WindowsMobile.Forms;
using System.Xml;
using System.Collections.Specialized;
using PocketLibrary;
using Microsoft.WindowsMobile.Status;
using System.Diagnostics;

namespace PocketApps
{
    public partial class flickrMain : Form
    {
        enum AnchorPosition
        {
            Top,
            Bottom,
            Left,
            Right,
            Center,
        }

        private class imageFile
        {
            public string FullName;
            public string FileName;
            public string Extension;
            public int ImageIndex;
            public string ShortName;

            public imageFile(string filename)
            {
                FullName = filename;
                FileName = filename.Substring(filename.LastIndexOf("\\") + 1);
                Extension = filename.Substring(filename.LastIndexOf("."));
                ShortName = FileName.Replace(this.Extension, "");
            }
        }

        ImageList localSmallImages;
        flickr myFlickr;
        List<flickrPhotoset> flickrSets;

        List<imageFile> imageFiles = new List<imageFile>();
        Thread uploadThread;
        bool uploading = false;
        // for storing available tags
        Dictionary<string, int> tags = new Dictionary<string, int>();
        List<string> searchLocations = new List<string>();
        int imagelistSmall = DpiHelper.Scale(32);
        //Thread cropThread;
        PocketSettings.PocketSettings milkSettings = PocketSettings.PocketSettings.Create();
        bool cameraAvailable = SystemState.CameraPresent;
        bool flickrActive = false;
        bool tagging = false;
        //PocketSettings.Settings settings = PocketSettings.Settings.Create();
        string thumbnailSize = "t";
        bool _abortThumbnailGeneration = false;

        Bitmap _previewPhoto = null;
        Bitmap _leftPhoto = null;
        Bitmap _rightPhoto = null;
        Bitmap _friendOverlayBitmap = null;
        Bitmap _familyOverlayBitmap = null;
        Color _friendTransparencyColor = new Color();
        Color _familyTransparencyColor = new Color();

        ImageList _contactImageList = new ImageList();

        flickrPhoto currPhoto, prevPhoto, nextPhoto = new flickrPhoto();

        XMLRPCCommunication downloader = new XMLRPCCommunication("");


        private string _currentPhotoSetId;
        public string CurrentPhotoSetId
        {
            get { return _currentPhotoSetId; }
        }

        private string _largeurl;
        public string PreviewImageUrl
        {
            get { return _largeurl; }
        }

        private string _phototitle;
        public string PhotoTitle
        {
            get { return _phototitle; }
        }

        private Rectangle _prevPhotoRegion;

        public Rectangle PrevPhotoRegion
        {
            get { return _prevPhotoRegion; }
            set { _prevPhotoRegion = value; }
        }

        private Rectangle _nextPhotoRegion;

        public Rectangle NextPhotoRegion
        {
            get { return _nextPhotoRegion; }
            set { _nextPhotoRegion = value; }
        }

        Bitmap Crop(Image imgPhoto, int Width, int Height, AnchorPosition Anchor)
        {
            int sourceWidth = imgPhoto.Width;
            int sourceHeight = imgPhoto.Height;
            int sourceX = 0;
            int sourceY = 0;
            int destX = 0;
            int destY = 0;

            float nPercent = 0;
            float nPercentW = 0;
            float nPercentH = 0;

            nPercentW = ((float)Width / (float)sourceWidth);
            nPercentH = ((float)Height / (float)sourceHeight);

            if (nPercentH < nPercentW)
            {
                nPercent = nPercentW;
                switch (Anchor)
                {
                    case AnchorPosition.Top:
                        destY = 0;
                        break;
                    case AnchorPosition.Bottom:
                        destY = (int)
                            (Height - (sourceHeight * nPercent));
                        break;
                    default:
                        destY = (int)
                            ((Height - (sourceHeight * nPercent)) / 2);
                        break;
                }
            }
            else
            {
                nPercent = nPercentH;
                switch (Anchor)
                {
                    case AnchorPosition.Left:
                        destX = 0;
                        break;
                    case AnchorPosition.Right:
                        destX = (int)
                          (Width - (sourceWidth * nPercent));
                        break;
                    default:
                        destX = (int)
                          ((Width - (sourceWidth * nPercent)) / 2);
                        break;
                }
            }

            int destWidth = (int)(sourceWidth * nPercent);
            int destHeight = (int)(sourceHeight * nPercent);

            Bitmap bmPhoto = new Bitmap(Width,
                    Height, PixelFormat.Format24bppRgb);
            //bmPhoto.SetResolution(imgPhoto.HorizontalResolution,
            //        imgPhoto.VerticalResolution);


            Graphics grPhoto = Graphics.FromImage(bmPhoto);
            //grPhoto.InterpolationMode =
            //        InterpolationMode.HighQualityBicubic;

            grPhoto.DrawImage(imgPhoto,
                new Rectangle(destX, destY, destWidth, destHeight),
                new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
                GraphicsUnit.Pixel);

            grPhoto.Dispose();
            return bmPhoto;
        }

        void UploadPhoto()
        {
            if (!uploading)
            {
                uploading = true;
                string filename = "";
                lvLocal.Invoke(new EventHandler(delegate
                {
                    filename = lvLocal.Items[lvLocal.SelectedIndices[0]].SubItems[1].Text;
                }));
                //myFlickr.UploadPhoto(filename);
                NameValueCollection flickrParams = new NameValueCollection();
                flickrParams.Add("title", lvLocal.Items[lvLocal.SelectedIndices[0]].Text);

                string imagetags = lvLocal.Items[lvLocal.SelectedIndices[0]].SubItems[2].Text;

                imagetags = imagetags.Replace(",", "");

                flickrParams.Add("tags", imagetags);
                myFlickr.FileUpload(filename, flickrParams);
                progressBar1.Invoke(new EventHandler(delegate
                {
                    progressBar1.Value = 0;
                }));
                uploading = false;
            }
        }

        public flickrMain()
        {
            InitializeComponent();
        }

        /// <summary>
        /// getTags from xml store
        /// </summary>
        private void getTags()
        {
            if (File.Exists(HelperUtils.ApplicationPath + "tags.xml"))
            {
                XmlDocument tagsxml = new XmlDocument();
                tagsxml.Load(HelperUtils.ApplicationPath + "tags.xml");
                XmlNodeList tagslist = tagsxml.SelectNodes("descendant::tags");
                foreach (XmlNode tag in tagslist)
                {
                    tags.Add(tag.InnerText, 1);
                }

            }
        }

        /// <summary>
        /// putTags to xml store, overwriting old tags
        /// </summary>
        private void putTags()
        {
        }

        private void getSearchLocations()
        {
            if (File.Exists(HelperUtils.ApplicationPath + "locations.xml"))
            {
                XmlDocument tagsxml = new XmlDocument();
                tagsxml.Load(HelperUtils.ApplicationPath + "locations.xml");
                XmlNodeList tagslist = tagsxml.SelectNodes("descendant::locations/imagelocation");
                foreach (XmlNode tag in tagslist)
                {
                    searchLocations.Add(tag.InnerText);
                }

            }
        }

        private void putSearcLocations()
        {
            if (File.Exists(HelperUtils.ApplicationPath + "locations.xml"))
                File.Delete(HelperUtils.ApplicationPath + "locations.xml");

            StringBuilder sb = new StringBuilder();
            sb.Append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
            sb.Append("<locations>");
            foreach (string location in searchLocations)
            {
                sb.Append("<imagelocation><![CDATA[" + location + "]]></imagelocation>");
            }
            sb.Append("</locations>");

            XmlDocument locationsxml = new XmlDocument();
            locationsxml.LoadXml(sb.ToString());
            locationsxml.Save(HelperUtils.ApplicationPath + "locations.xml");
        }

        private void flickrMain_Load(object sender, EventArgs e)
        {
            myFlickr = new flickr(milkSettings.SelectedUserProfile.Settings.Get("flickrToken"));
            myFlickr.OnUploadProgress += new PocketLibrary.UploadProgressHandler(myFlickr_OnUploadProgress);
            myFlickr.OnContactListResponse += new flickrResponseHandler(myFlickr_OnContactListResponse);
            myFlickr.OnPhotoSetListResponse += new flickrResponseHandler(myFlickr_OnPhotoSetListResponse);
            myFlickr.OnPhotoListResponse += new flickrResponseHandler(myFlickr_OnPhotoListResponse);

            downloader.OnDownloadProgress += new UploadProgressHandler(downloader_OnDownloadProgress);

            //chFilename.Width = this.Width;
            //getTags();
            getSearchLocations();
            //searchLocations.Add(Settings.DataPath);
            listLocalImages();
            lvLocal.View = View.Details;
            miLargeIcon.Checked = false;
            miLargeIcon2.Checked = false;
            miSmallIcon.Checked = false;
            miList.Checked = false;
            miDetails.Checked = true;
            miDetails2.Checked = true;

            localSmallImages = new ImageList();
            localSmallImages.ImageSize = new Size(imagelistSmall, imagelistSmall);

            _friendOverlayBitmap = new Bitmap(16, 16);
            _friendOverlayBitmap = new Bitmap(HelperUtils.ApplicationPath + "\\settings\\group.png");

            _familyOverlayBitmap = new Bitmap(16, 16);
            _familyOverlayBitmap = new Bitmap(HelperUtils.ApplicationPath + "\\settings\\heart.png");

            _friendTransparencyColor = _friendOverlayBitmap.GetPixel(1, 1);
            _familyTransparencyColor = _familyOverlayBitmap.GetPixel(1, 1);

            //localSmallImages.Images.Add(imageList1.Images[0]);
            //lvFlickr.Items[0].ImageIndex = 0;

            //lvLocal.SmallImageList = localSmallImages;
            //lvLocal.LargeImageList = localSmallImages;

            buildMenu();

            if (!cameraAvailable)
                miTakePicture.Enabled = false;

            getThumbnailSize();
        }

        void downloader_OnDownloadProgress(object sender, UploadProgressEventArgs e)
        {
            progressBar1.Invoke(new EventHandler(delegate
            {
                if (!e.Complete)
                    progressBar1.Value = e.CurrentProgress;
                else
                    progressBar1.Value = 0;
            }));
        }

        private void getThumbnailSize()
        {
            string temp = milkSettings.SelectedUserProfile.Settings.Get("flickrPreviewSize");
            if (temp == "Thumbnail")
                thumbnailSize = "t";
            else if (temp == "Small")
                thumbnailSize = "s";
            else if (temp == "Medium")
                thumbnailSize = "m";
            else if (temp == "Normal")
                thumbnailSize = "l";

            temp = milkSettings.SelectedUserProfile.Settings.Get("localPreviewSize");
            if (temp == "Thumbnail")
                imagelistSmall = 24;
            else if (temp == "Small")
                imagelistSmall = 32;
            else if (temp == "Medium")
                imagelistSmall = 48;
            else if (temp == "Normal")
                imagelistSmall = 64;

        }

        void myFlickr_OnPhotoListResponse(object sender, EventArgs args)
        {
            lvFlickr.Invoke(new EventHandler(delegate
            {
                lvFlickrPhotos.Items.Clear();
                for (int i = 0; i < myFlickr.CurrentPhotos.Count; i++)
                {
                    flickrListViewItem photoitem = new flickrListViewItem();
                    photoitem.Text = myFlickr.CurrentPhotos[i].Title;
                    photoitem.SubItems.Add(myFlickr.CurrentPhotos[i].Id);
                    photoitem.SubItems.Add(myFlickr.CurrentPhotos[i].ThumbnailUrl);
                    photoitem.PhotoData = myFlickr.CurrentPhotos[i];
                    lvFlickrPhotos.Items.Add(photoitem);
                }
            }));

            // switch to photo view
            tcFlickr.Invoke(new EventHandler(delegate
            {
                tcFlickr.SelectedIndex = 1;
            }));
        }

        void myFlickr_OnPhotoSetListResponse(object sender, EventArgs args)
        {
            if (myFlickr.PhotoSets.Count > 0)
            {
                lvFlickr.Invoke(new EventHandler(delegate
                {
                    lvFlickr.Items.Clear();
                    for (int i = 0; i < myFlickr.PhotoSets.Count; i++)
                    {
                        //lbPhotosets.Items.Add(myFlickr.PhotoSets[i].Title);
                        ListViewItem flickrItem = new ListViewItem();
                        flickrItem.Text = myFlickr.PhotoSets[i].Title;
                        flickrItem.SubItems.Add(myFlickr.PhotoSets[i].PhotoCount.ToString());
                        flickrItem.SubItems.Add(myFlickr.PhotoSets[i].Id);
                        flickrItem.SubItems.Add(myFlickr.PhotoSets[i].Description);

                        // add photosets to listview
                        lvFlickr.Items.Add(flickrItem);
                    }

                    lvFlickr.Items.Add(new ListViewItem(
                        new string[] {
                            "photos not in set", // title
                            "n/a",  // photo count
                            "0", // id
                            "Photos not assigned to any sets" // description
                        }));
                }));
            }
            else
            {
                lvFlickr.Invoke(new EventHandler(delegate
                {
                    lvFlickr.Items.Add(new ListViewItem(
                        new string[] {
                            "no photosets returned", // title
                            "n/a",  // photo count
                            "0", // id
                            "Photos not assigned to any sets" // description
                        }));
                }));
            }
        }

        void myFlickr_OnContactListResponse(object sender, EventArgs args)
        {
            if (myFlickr.CurrentContacts.Count > 0)
            {
                lvFlickrContacts.Invoke(new EventHandler(delegate
                {
                    lvFlickrContacts.Items.Clear();
                    _contactImageList.Images.Clear();
                    _contactImageList.ImageSize = new Size(48, 48);
                    for (int i = 0; i < myFlickr.CurrentContacts.Count; i++)
                    {
                        ListViewItem contactitem = new ListViewItem(new string[]
                            {
                                myFlickr.CurrentContacts[i].RealName,
                                myFlickr.CurrentContacts[i].Id
                            });
                        contactitem.ImageIndex = i;
                        lvFlickrContacts.Items.Add(contactitem);
                    }

                    lvFlickrContacts.SmallImageList = _contactImageList;

                }));

                if (milkSettings.SelectedUserProfile.Settings.Get("flickrDownloadBuddyIcons") == "true")
                    ThreadPool.QueueUserWorkItem(new WaitCallback(loadBuddyIcons));
            }
        }

        private void loadBuddyIcons(object stateInfo)
        {
            if (_contactImageList.Images.Count != myFlickr.CurrentContacts.Count
                )
            {
                _contactImageList.Images.Clear();
                _contactImageList.ImageSize = new Size(48, 48);

                for (int i = 0; i < myFlickr.CurrentContacts.Count; i++)
                {

                    Bitmap _contactBitmap = new Bitmap(48, 48);
                    Graphics _contactGraphics = Graphics.FromImage(_contactBitmap);
                    ImageAttributes attr = new ImageAttributes();
                    _contactGraphics.DrawImage(
                        myFlickr.GetContactBuddyIcons(myFlickr.CurrentContacts[i]), 0, 0);

                    if (myFlickr.CurrentContacts[i].IsFamily == "1")
                    {
                        attr.SetColorKey(_familyTransparencyColor, _familyTransparencyColor);

                        _contactGraphics.DrawImage(
                            _familyOverlayBitmap,
                            new Rectangle(0, 32, 16, 16),
                            0, 0, 16, 16,
                            GraphicsUnit.Pixel,
                            attr
                            );
                    }

                    if (myFlickr.CurrentContacts[i].IsFriend == "1")
                    {
                        attr.SetColorKey(_friendTransparencyColor, _friendTransparencyColor);
                        //_contactGraphics.DrawImage(
                        //    _friendOverlayBitmap, 32, 32);
                        _contactGraphics.DrawImage(
                            _friendOverlayBitmap,
                            new Rectangle(32, 32, 16, 16),
                            0, 0, 16, 16,
                            GraphicsUnit.Pixel,
                            attr
                            );

                    }
                    _contactGraphics.Dispose();
                    _contactImageList.Images.Add(_contactBitmap);
                }
            }

            lvFlickrContacts.Invoke(new EventHandler(delegate
            {
                lvFlickrContacts.Invalidate();
            }));
        }

        void myFlickr_OnUploadProgress(object sender, PocketLibrary.UploadProgressEventArgs e)
        {
            progressBar1.Invoke(new EventHandler(delegate
            {
                progressBar1.Value = (int)((e.Bytes / myFlickr.PhotoFilesize) * 100);
            }));
        }

        void listLocalImages()
        {
            for (int i = 0; i < searchLocations.Count; i++)
            {
                listLocalImages(searchLocations[i]);
            }
        }

        private void listLocalImages(string directory)
        {
            FileInfo[] files = new DirectoryInfo(directory).GetFiles("*.jpg");
            foreach (FileInfo finfo in files)
            {
                imageFile imgfile = new imageFile(finfo.FullName);
                imgfile.ImageIndex = imageFiles.Count;
                imageFiles.Add(imgfile);
            }

            /*
            files = new DirectoryInfo(location).GetFiles("*.png");

            foreach (FileInfo finfo in files)
            {
                imageFile imgfile = new imageFile();
                imgfile.FullName = finfo.FullName;
                imgfile.FileName = finfo.Name;
                imgfile.Extension = finfo.Extension;
                imageFiles.Add(imgfile);
            }
            /**/


            foreach (imageFile file in imageFiles)
            {
                ListViewItem lvitem = new ListViewItem();
                lvitem.Text = file.ShortName;
                lvitem.SubItems.Add("no tags");
                lvitem.SubItems.Add(file.FullName);
                lvLocal.Items.Add(lvitem);
                lvLocal.Items[lvLocal.Items.Count - 1].ImageIndex = file.ImageIndex;
            }
        }

        private void generateThumbnails(object stateInfo)
        {
            try
            {
                // clear images and start with empty imagelist
                localSmallImages.Images.Clear();

                //localSmallImages.Images.Add(imageList1.Images[0]);
                //lvFlickr.Invoke(new EventHandler(delegate
                //{
                //    lvFlickr.Items[0].ImageIndex = 0;
                //}));

                foreach (imageFile file in imageFiles)
                {
                    try
                    {
                        using (Bitmap bm = new Bitmap(imagelistSmall, imagelistSmall))
                        {
                            Bitmap cropped = Crop(
                                new Bitmap(file.FullName),
                                imagelistSmall, imagelistSmall, AnchorPosition.Center);
                            // add cropped image to imagelist
                            localSmallImages.Images.Add(cropped);
                        }
                    }
                    catch (OutOfMemoryException)
                    {
                        GC.WaitForPendingFinalizers();
                        using (Bitmap bm = new Bitmap(imagelistSmall, imagelistSmall))
                        {
                            Bitmap cropped = Crop(
                                new Bitmap(file.FullName),
                                imagelistSmall, imagelistSmall, AnchorPosition.Center);
                            // add cropped image to imagelist
                            localSmallImages.Images.Add(cropped);
                        }
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine("image load failed");
                        localSmallImages.Images.Add(new Bitmap(imagelistSmall, imagelistSmall));
                    }

                    // update listview contents with new image
                    if (lvLocal.InvokeRequired)
                    {
                        lvLocal.Invoke(new EventHandler(delegate
                        {
                            lvLocal.Invalidate();
                        }));
                    }
                    if (_abortThumbnailGeneration)
                    {
                        _abortThumbnailGeneration = false;
                        return;
                    }
                }
            }
            catch (ThreadAbortException)
            {
            }
            //catch (OutOfMemoryException)
            //{
            //    MessageBox.Show("We ran out of memory. Stopping.", "Out of memory");
            //}
            finally
            {
                if (this.InvokeRequired)
                {
                    this.BeginInvoke(new EventHandler(delegate
                    {
                        miGenThumbnails.Text = "Generate thumbnails";
                    }));
                }
                else
                {
                    miGenThumbnails.Text = "Generate thumbnails";
                }
                this.GeneratingThumbnails = false;

            }
        }

        private void miLargeIcon_Click(object sender, EventArgs e)
        {
            lvLocal.View = View.LargeIcon;
            miLargeIcon.Checked = true;
            miSmallIcon.Checked = false;
            miList.Checked = false;
            miDetails.Checked = false;
            miLargeIcon2.Checked = true;
            miSmallIcon2.Checked = false;
            miList2.Checked = false;
            miDetails2.Checked = false;
            lvLocal.CheckBoxes = false;

        }

        private void miSmallIcon_Click(object sender, EventArgs e)
        {
            lvLocal.View = View.SmallIcon;
            miLargeIcon.Checked = false;
            miSmallIcon.Checked = true;
            miList.Checked = false;
            miDetails.Checked = false;

            miLargeIcon2.Checked = false;
            miSmallIcon2.Checked = true;
            miList2.Checked = false;
            miDetails2.Checked = false;
            lvLocal.CheckBoxes = false;
        }

        private void miList_Click(object sender, EventArgs e)
        {
            lvLocal.View = View.List;
            miLargeIcon.Checked = false;
            miSmallIcon.Checked = false;
            miList.Checked = true;
            miDetails.Checked = false;

            miLargeIcon2.Checked = false;
            miSmallIcon2.Checked = false;
            miList2.Checked = true;
            miDetails2.Checked = false;
            lvLocal.CheckBoxes = false;
        }

        private void miDetails_Click(object sender, EventArgs e)
        {
            lvLocal.View = View.Details;
            miLargeIcon.Checked = false;
            miSmallIcon.Checked = false;
            miList.Checked = false;
            miDetails.Checked = true;

            miLargeIcon2.Checked = false;
            miSmallIcon2.Checked = false;
            miList2.Checked = false;
            miDetails2.Checked = true;
            lvLocal.CheckBoxes = false;

        }

        private void menuItem1_Click(object sender, EventArgs e)
        {
            if (lvLocal.SelectedIndices.Count > 0)
            {
                progressBar1.Value = 0;
                progressBar1.Visible = true;
                uploadThread = new Thread(UploadPhoto);
                uploadThread.IsBackground = true;
                uploadThread.Start();

            }
        }

        private void getCameraPicture()
        {
            CameraCaptureDialog ccd = new CameraCaptureDialog();
            ccd.Mode = CameraCaptureMode.Still;
            ccd.StillQuality = CameraCaptureStillQuality.Default;

            string fileName = string.Empty;
            ccd.DefaultFileName = "flickr-" + DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss") + ".jpg";

            try
            {
                ccd.ShowDialog();
                fileName = ccd.FileName;

                //using (Bitmap bm = new Bitmap(fileName))
                //{
                //    localSmallImages.Images.Add(Crop(bm, small, small, AnchorPosition.Center));
                //}

                string shortName = fileName.Substring(fileName.LastIndexOf("\\") + 1);
                shortName = shortName.Substring(0, shortName.LastIndexOf('.'));
                ListViewItem lvitem = new ListViewItem(shortName);
                lvitem.Text = shortName;
                lvitem.SubItems.Add("no tags");
                lvitem.SubItems.Add(fileName);

                //lvitem.ImageIndex = localSmallImages.Images.Count - 1;
                lvLocal.Items.Add(lvitem);
                //listView1.Items[listView1.Items.Count - 1].ImageIndex = localLargeImages.Images.Count - 1;
            }
            catch (InvalidOperationException)
            {
                MessageBox.Show("Kuvan ottaminen ei onnistu", "Kamera");
            }
            finally
            {
                this.Show();
                ccd.Dispose();
            }
        }

        private void menuItem4_Click(object sender, EventArgs e)
        {
            using (PickFolder pickdatafolder = new PickFolder())
            {
                if (pickdatafolder.ShowDialog() == DialogResult.OK)
                {
                    searchLocations.Add(pickdatafolder.SelectedFolder);
                    // save locations to disk
                    putSearcLocations();
                    // clear location list
                    searchLocations.Clear();
                    // get locations from disk
                    getSearchLocations();
                    // list images
                    listLocalImages();
                }
            }
        }

        private void flickrMain_Closing(object sender, CancelEventArgs e)
        {
            _abortThumbnailGeneration = true;
            //if (cropThread != null)
            //    cropThread.Abort();
        }

        private void tagSelected_Click(object sender, EventArgs e)
        {
            this.SuspendLayout();
            if (lvLocal.SelectedIndices.Count > 0)
            {
                tagging = true;
                string imagelocation = lvLocal.Items[lvLocal.SelectedIndices[0]].SubItems[2].Text;
                FileInfo image = new FileInfo(imagelocation);
                //byte[] imagedata = new byte[image.Length];
                //using (BinaryReader sr = new BinaryReader(image.OpenRead()))
                //{
                //    sr.Read(imagedata, 0, (int)image.Length);
                //}
                //MemoryStream ms = new MemoryStream(imagedata);

                //picPreview.Image = Image.
                try
                {
                    if (picPreview.Image != null)
                        picPreview.Image = null;
                    picPreview.Image = new Bitmap(picPreview.Width, picPreview.Height);
                    picPreview.Image = Crop(new Bitmap(imagelocation),
                     picPreview.Width, picPreview.Height, AnchorPosition.Center);
                }
                catch (OutOfMemoryException)
                {
                    GC.WaitForPendingFinalizers();
                    picPreview.Image = new Bitmap(picPreview.Width, picPreview.Height);
                    picPreview.Image = Crop(new Bitmap(imagelocation),
                     picPreview.Width, picPreview.Height, AnchorPosition.Center);

                }
                catch (Exception)
                {
                    //GC.WaitForPendingFinalizers();
                    Debug.WriteLine("image load failed");
                }
                tbName.Text = lvLocal.Items[lvLocal.SelectedIndices[0]].Text;
                tbTags.Text = lvLocal.Items[lvLocal.SelectedIndices[0]].SubItems[1].Text;
                panTags.Visible = true;
                panLocal.Visible = false;
                miAction.Text = "Ok";
            }
            this.ResumeLayout();
        }

        private void bnApply_Click(object sender, EventArgs e)
        {
            this.SuspendLayout();
            lvLocal.Items[lvLocal.SelectedIndices[0]].Text = tbName.Text;
            lvLocal.Items[lvLocal.SelectedIndices[0]].SubItems[1].Text = tbTags.Text;
            panLocal.Visible = true;
            panTags.Visible = false;
            tagging = false;
            miAction.Text = "Valitse";
            picPreview.Image = null;
            this.ResumeLayout();
        }

        private bool generating;

        public bool GeneratingThumbnails
        {
            get { return generating; }
            set { generating = value; }
        }

        private void menuItem8_Click(object sender, EventArgs e)
        {
            if (GeneratingThumbnails)
            {
                //cropThread.Abort();
                _abortThumbnailGeneration = true;
                miGenThumbnails.Text = "Generate thumbnails";
                this.GeneratingThumbnails = false;
            }
            else
            {
                this.GeneratingThumbnails = true;
                miGenThumbnails.Text = "Stop generating";
                lvLocal.SmallImageList = localSmallImages;
                lvLocal.LargeImageList = localSmallImages;
                //cropThread = new Thread(generateThumbnails);
                //cropThread.IsBackground = true;
                //cropThread.Start();
                ThreadPool.QueueUserWorkItem(new WaitCallback(generateThumbnails));
            }
        }

        private void miClose_Click(object sender, EventArgs e)
        {
            putTags();
            putSearcLocations();

            this.DialogResult = DialogResult.OK;
        }

        private void miTakePicture_Click(object sender, EventArgs e)
        {
            if (!flickrActive)
                getCameraPicture();
            else
                uploadCameraPicture();
        }

        private void uploadCameraPicture()
        {
            using (CameraCaptureDialog ccd = new CameraCaptureDialog())
            {
                List<string> images = new List<string>();
                ccd.Owner = null;
                ccd.Title = "flickr Camera";
                ccd.Mode = CameraCaptureMode.Still;
                ccd.StillQuality = CameraCaptureStillQuality.Default;

                do
                {
                    ccd.DefaultFileName = "flickr-" + DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss") + ".jpg";

                    if (DialogResult.OK == ccd.ShowDialog())
                        images.Add(ccd.FileName);

                } while (
                     MessageBox.Show("Take a new picture",
                     "Camera",
                     MessageBoxButtons.YesNo,
                     MessageBoxIcon.Question,
                     MessageBoxDefaultButton.Button1) == DialogResult.Yes);

                foreach (string imagename in images)
                {
                    myFlickr.UploadPhoto(imagename);
                }
            }

        }

        private void miAction_Click(object sender, EventArgs e)
        {
            if (tagging)
                bnApply_Click(this, e);
            else if (lvLocal.Focused && lvLocal.SelectedIndices.Count > 0)
                tagSelected_Click(sender, e);
            else if (lvFlickr.Focused)
                lvFlickr_ItemActivate(sender, e);
            else if (pbFlickrPreview.Focused)
            {
                using (SaveFileDialog sfd = new SaveFileDialog())
                {
                    sfd.Filter = "Jpeg|*.jpg";
                    sfd.FileName = PhotoTitle;
                    if (sfd.ShowDialog() == DialogResult.OK)
                    {
                        Bitmap downloaded = downloader.DownloadBitmap(PreviewImageUrl);
                        downloaded.Save(sfd.FileName, ImageFormat.Jpeg);
                    }
                }
            }


        }

        private void miShowFlickr_Click(object sender, EventArgs e)
        {
            this.SuspendLayout();
            panLocal.Visible = !panLocal.Visible;
            panFlickr.Visible = !panFlickr.Visible;
            flickrActive = !flickrActive;

            if (flickrActive)
            {
                myFlickr.GetPhotoSets(null);
                tcFlickr.TabIndex = 0;
                lvFlickr.Focus();
            }

            buildMenu();

            this.ResumeLayout();
        }

        private void buildMenu()
        {

            if (flickrActive)
            {
                miMenu.MenuItems.Clear();
                miMenu.MenuItems.Add(miTakePicture);
                // add flickr menuitems here
                miMenu.MenuItems.Add(miFlickrMySets);
                miMenu.MenuItems.Add(miFlickrPhotosetMgr);
                miMenu.MenuItems.Add(miFlickrDn);
                miMenu.MenuItems.Add(miFlickrSettings);
                // -------------------------
                miMenu.MenuItems.Add(miSep);
                miMenu.MenuItems.Add(miShowFlickr);

                miMenu.MenuItems.Add(miClose);
            }
            else
            {
                miMenu.MenuItems.Clear();
                miMenu.MenuItems.Add(miTakePicture);
                miMenu.MenuItems.Add(miUploadSelected);
                miMenu.MenuItems.Add(miTagSelected);
                miMenu.MenuItems.Add(miGenThumbnails);
                miMenu.MenuItems.Add(miAddLocation);
                miMenu.MenuItems.Add(miFlickrSettings);
                miMenu.MenuItems.Add(miSep);
                miMenu.MenuItems.Add(miShowFlickr);
                miMenu.MenuItems.Add(miViews);
                miMenu.MenuItems.Add(miClose);

            }

        }

        private void lvFlickr_SelectedIndexChanged(object sender, EventArgs e)
        {
            // show description
            if (lvFlickr.SelectedIndices.Count == 1)
            {
                tbMeta.Text =
                    lvFlickr.Items[lvFlickr.SelectedIndices[0]].SubItems[3].Text;
            }
            else
                tbMeta.Text = "";
        }

        private void lvFlickr_ItemActivate(object sender, EventArgs e)
        {
            if (lvFlickr.SelectedIndices.Count == 1)
            {
                string photosetid = lvFlickr.Items[lvFlickr.SelectedIndices[0]].SubItems[2].Text;
                if (photosetid != "0")
                {
                    _currentPhotoSetId = photosetid;
                    myFlickr.GetSetPhotos(photosetid);
                }
                else
                {
                    if (nsid == "0")
                    {
                        _currentPhotoSetId = "0";
                        myFlickr.GetPhotosNotInSet();
                    }
                    else
                    {
                        _currentPhotoSetId = "0";
                        myFlickr.GetPeoplePublicPhotos(nsid);
                    }
                }
            }
        }

        private void lvFlickrPhotos_ItemActivate(object sender, EventArgs e)
        {
            if (lvFlickrPhotos.SelectedIndices.Count == 1)
            {
                pbFlickrPreview.Dock = DockStyle.Fill;
                //pbFlickrPreview.Image = PocketLibrary.XMLRPCCommunication.DownloadBitmap(
                //    (flickrListViewItem)(lvFlickrPhotos.Items[lvFlickrPhotos.SelectedIndices[0]])
                //    );
                flickrListViewItem item = (flickrListViewItem)lvFlickrPhotos.Items[lvFlickrPhotos.SelectedIndices[0]];

                updateSlideShow(item.PhotoData);

                panFlickr.Visible = false;
                pbFlickrPreview.Visible = true;
                pbFlickrPreview.Focus();
            }
        }

        Rectangle _leftRect, _rightRect;
        private void updateSlideShow(flickrPhoto item)
        {
            _largeurl = item.LargeUrl;
            _phototitle = item.Title;

            flickrPhoto[] context;

            if (CurrentPhotoSetId != "0")
                context = myFlickr.GetPhotosetContext(CurrentPhotoSetId, item.Id);
            else
                context = myFlickr.GetPhotosContext(item.Id);
            item.ThumbnailSize = this.thumbnailSize;
            context[0].ThumbnailSize = "s";
            context[1].ThumbnailSize = "s";
            currPhoto = item;
            prevPhoto = context[0];
            nextPhoto = context[1];
            _previewPhoto = null;
            _leftPhoto = null;
            _rightPhoto = null;

            if (pbFlickrPreview.Image != null)
                pbFlickrPreview.Image = null;

            pbFlickrPreview.Image = new Bitmap(pbFlickrPreview.Width, pbFlickrPreview.Height);

            float centerH = ((float)pbFlickrPreview.Height / 2);
            float centerW = ((float)pbFlickrPreview.Width / 2);

            Graphics gg = Graphics.FromImage(pbFlickrPreview.Image);
            gg.Clear(Color.Silver);

            if (_previewPhoto == null)
                _previewPhoto = downloader.DownloadBitmap(currPhoto.ThumbnailUrl);

            gg.DrawImage(_previewPhoto,
                (int)(centerW - ((float)_previewPhoto.Width / 2)),
                (int)(centerH - ((float)_previewPhoto.Height / 2)));

            if (prevPhoto.Id != "0")
            {
                #region draw previous photo
                if (_leftPhoto == null)
                    _leftPhoto = downloader.DownloadBitmap(prevPhoto.ThumbnailUrl);

                _prevPhotoRegion = new Rectangle(
                    0,
                    (int)(centerH - ((float)_leftPhoto.Height)),
                    _leftPhoto.Width,
                    _leftPhoto.Height);

                if (_leftRect != null)
                    _leftRect = new Rectangle(0, 0, _leftPhoto.Width, _leftPhoto.Height);

                gg.FillRectangle(new SolidBrush(Color.White),
                    new Rectangle(
                    0,
                    (int)(centerH - ((float)_leftPhoto.Height) - 2),
                    _leftPhoto.Width + 2, _leftPhoto.Height + 4));

                gg.DrawImage(_leftPhoto, 0,
                    (int)(centerH - ((float)_leftPhoto.Height)));

                gg.DrawImage(_leftPhoto,
                    _prevPhotoRegion,
                    _leftRect, GraphicsUnit.Pixel);

                #endregion
            }
            else
                _prevPhotoRegion = new Rectangle();

            if (nextPhoto.Id != "0")
            {
                #region draw next photo
                if (_rightPhoto == null)
                    _rightPhoto = downloader.DownloadBitmap(nextPhoto.ThumbnailUrl);

                gg.FillRectangle(new SolidBrush(Color.White),
                    new Rectangle(
                    pbFlickrPreview.Width - _rightPhoto.Width - 2,
                    (int)(centerH - ((float)_rightPhoto.Height) - 2),
                    _rightPhoto.Width, _rightPhoto.Height + 4));

                gg.DrawImage(_rightPhoto, pbFlickrPreview.Width - _rightPhoto.Width,
                    (int)(centerH - ((float)_rightPhoto.Height)));

                _nextPhotoRegion = new Rectangle(
                    pbFlickrPreview.Width - _rightPhoto.Width,
                    (int)(centerH - ((float)_rightPhoto.Height)),
                    _rightPhoto.Width,
                    _rightPhoto.Height);
                #endregion
            }
            else
                _nextPhotoRegion = new Rectangle();

            // TODO: draw toolbar


            gg.Dispose();
        }

        Rectangle hitRect = new Rectangle();

        private void pbFlickrPreview_Click(object sender, EventArgs e)
        {
            if (PrevPhotoRegion.IntersectsWith(hitRect))
            {
                Debug.WriteLine("prev photo");
                updateSlideShow(prevPhoto);

            }
            else if (NextPhotoRegion.IntersectsWith(hitRect))
            {
                Debug.WriteLine("next photo");
                updateSlideShow(nextPhoto);
            }
            else
            {
                Debug.WriteLine("photo clicked");
                pbFlickrPreview.Visible = false;
                panFlickr.Visible = true;
                pbFlickrPreview.Image = null;
                lvFlickrPhotos.Focus();
            }
        }

        private void miMenu_Popup(object sender, EventArgs e)
        {

        }

        private void tcFlickr_SelectedIndexChanged(object sender, EventArgs e)
        {
            miFlickrDn.Enabled = false;
            pbFlickrPreview.Visible = false;
            if (tcFlickr.SelectedIndex == 0)
            {
                lvFlickr.Focus();
            }
            else if (tcFlickr.SelectedIndex == 1)
            {
                miFlickrDn.Enabled = true;
                lvFlickrPhotos.Focus();
            }
            else if (tcFlickr.SelectedIndex == 2)
            {
                if (myFlickr.CurrentContacts.Count == 0)
                {
                    myFlickr.GetContacts();
                }
                lvFlickrContacts.Focus();

            }
        }

        string nsid = "0";

        private void lvFlickrContacts_ItemActivate(object sender, EventArgs e)
        {
            string itemid = lvFlickrContacts.Items[lvFlickrContacts.SelectedIndices[0]].SubItems[1].Text;
            lvFlickr.Items.Clear();
            nsid = itemid;
            myFlickr.GetPhotoSets(itemid);
            tcFlickr.SelectedIndex = 0;
        }

        private void miFlickrSettings_Click(object sender, EventArgs e)
        {
            using (flickrSettings fset = new flickrSettings())
            {
                if (fset.ShowDialog() == DialogResult.OK)
                    getThumbnailSize();

            }
        }

        private void lvFlickrPhotos_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void flickrMain_KeyDown(object sender, KeyEventArgs e)
        {
            if ((e.KeyCode == System.Windows.Forms.Keys.Up))
            {
                // Up
                if (pbFlickrPreview.Focused)
                {
                    pbFlickrPreview.Visible = false;
                    pbFlickrPreview.Image = null;
                    panFlickr.Visible = true;
                }
            }
            if ((e.KeyCode == System.Windows.Forms.Keys.Down))
            {
                // Down
                if (pbFlickrPreview.Focused)
                {
                    pbFlickrPreview.Visible = false;
                    pbFlickrPreview.Image = null;
                    panFlickr.Visible = true;
                }
            }
            if ((e.KeyCode == System.Windows.Forms.Keys.Left))
            {
                // Left
                if (pbFlickrPreview.Focused && prevPhoto.Id != "0")
                    updateSlideShow(prevPhoto);
            }
            if ((e.KeyCode == System.Windows.Forms.Keys.Right))
            {
                // Right
                if (pbFlickrPreview.Focused && nextPhoto.Id != "0")
                    updateSlideShow(nextPhoto);
            }
            if ((e.KeyCode == System.Windows.Forms.Keys.Enter))
            {
                // Enter
                if (pbFlickrPreview.Focused)
                {
                    pbFlickrPreview.Visible = false;
                    pbFlickrPreview.Image = null;
                    panFlickr.Visible = true;
                }
            }

        }

        private void pbFlickrPreview_MouseUp(object sender, MouseEventArgs e)
        {
        }

        private void pbFlickrPreview_MouseDown(object sender, MouseEventArgs e)
        {
            hitRect = new Rectangle(e.X, e.Y, 1, 1);

        }

        private void pbFlickrPreview_Paint(object sender, PaintEventArgs e)
        {

        }

        private void miFlickrMySets_Click(object sender, EventArgs e)
        {
            nsid = "0";
            myFlickr.GetPhotoSets("0");
        }

        private void miFlickrPhotosetMgr_Click(object sender, EventArgs e)
        {
            using (flickrPhotoSetMgr mgr = new flickrPhotoSetMgr())
            {
                mgr.ShowDialog();
                myFlickr.GetPhotoSets("0");
            }
        }

    }

    class flickrListViewItem : ListViewItem
    {
        private flickrPhoto _photo;

        public flickrPhoto PhotoData
        {
            get { return _photo; }
            set { _photo = value; }
        }
    }
}